﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace calculator
{
    class PerformOperation
    {
        private string[] validOperations = new string[]{"AND","OR","XOR","NOT","NAND","NOR","IFF","IFN","XNOR"};
        private Dictionary<string, Operation> mappedObjects = new Dictionary<string, Operation>();
        /*
         Valid operations are:
         * AND
         * OR
         * XOR which is exclusive OR
         * NOT
         * NAND which is NOT AND
         * NOR which is NOT OR
         * IFF which is IF AND ONLY IF (This can also be called XNOR which is Exclusive Not Or)
         * IFN which is IF THEN
         */

        public PerformOperation()
        {
            //NOT operation is not added since it has it's own function in this class
            mappedObjects.Add("OR", new OrOperation());
            mappedObjects.Add("AND", new AndOperation());
            mappedObjects.Add("XOR", new XorOperation());
            mappedObjects.Add("NAND", new NandOperation());
            mappedObjects.Add("NOR", new NorOperation());
            mappedObjects.Add("IFF", new IffOperation());
            mappedObjects.Add("XNOR", new IffOperation());
            mappedObjects.Add("IFN", new IfnOperation());

        }

        private bool isValidOperation(string operationToCheck)
        {
            bool isValid = false;

            foreach (string validOperation in validOperations)
            {
                if (validOperation == operationToCheck.ToUpper())
                    isValid = true;
            }
            return isValid;
        }

        public bool[] resultOfOperation(bool[] firstOperator, bool[] secondOperator, string operation)
        {
            bool[] resultFromOperations = new bool[firstOperator.Length];
            for (int index = 0; index < firstOperator.Length; index++)
            {
                resultFromOperations[index] = resultOfOperation(firstOperator[index], secondOperator[index], operation);
            }
            return resultFromOperations;
        }

        public bool resultOfOperation(bool firstOperator, bool secondOperator, string operation)
        {
            foreach (KeyValuePair<string, Operation> keyAndValue in mappedObjects)
            {
                if (keyAndValue.Key == operation.ToUpper())
                    return mappedObjects[keyAndValue.Key].doOperation(firstOperator,secondOperator);
            }

            throw new ArgumentException("Something has gone very wrong.");
        }

        public bool resultOfOperation(bool onlyOperation, string operation)//This will take care of NOT operation
        {
            if (operation.ToUpper() != "NOT")
                throw new ArgumentException("Only the NOT operation can have one operator");
            return !onlyOperation;
        }

        public bool[] resultOfOperation(bool[] onlyOperation, string operation)//This will take care of NOT operation for bool array
        {
            if (operation.ToUpper() != "NOT")
                throw new ArgumentException("Only the NOT operation can have one operator");

            for (int index = 0; index < onlyOperation.Length; index++)
            {
                onlyOperation[index] = !onlyOperation[index];
            }

            return onlyOperation;
        }
    }
}
